.long SYMBOL_NAME(do_set_debugreg)
.long SYMBOL_NAME(do_get_debugreg)
.long SYMBOL_NAME(do_update_descriptor)
+ .long SYMBOL_NAME(do_set_fast_trap)
.rept NR_syscalls-(.-hypervisor_call_table)/4
.long SYMBOL_NAME(sys_ni_syscall)
.endr
/*
* ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
- * (these are usually mapped to vectors 0x20-0x2f)
+ * (these are usually mapped to vectors 0x30-0x3f)
*/
BUILD_16_IRQS(0x0)
BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
- BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
+ BUILD_16_IRQS(0xc)
#endif
#undef BUILD_16_IRQS
IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
- IRQLIST_16(0xc), IRQLIST_16(0xd)
+ IRQLIST_16(0xc)
#endif
};
* outb_p - this has to work on a wide range of PC hardware.
*/
outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */
- outb_p(0x20 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
+ outb_p(0x30 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 */
outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */
if (auto_eoi)
outb_p(0x03, 0x21); /* master does Auto EOI */
outb_p(0x01, 0x21); /* master expects normal EOI */
outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */
- outb_p(0x20 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
+ outb_p(0x30 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x38-0x3f */
outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */
outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode
is to be investigated) */
return IO_APIC_VECTOR(irq);
next:
current_vector += 8;
- if (current_vector == HYPERVISOR_CALL_VECTOR)
- goto next;
+ /* XXX Skip the guestOS -> Xen syscall vector! XXX */
+ if (current_vector == HYPERVISOR_CALL_VECTOR) goto next;
+ /* XXX Skip the Linux/BSD fast-trap vector! XXX */
+ if (current_vector == 0x80) goto next;
if (current_vector > FIRST_SYSTEM_VECTOR) {
offset++;
__save_flags(regs->eflags);
regs->eflags |= X86_EFLAGS_IF;
+
+ /* No fast trap at start of day. */
+ p->thread.fast_trap_idx = 0x20;
+ p->thread.fast_trap_desc.a = 0;
+ p->thread.fast_trap_desc.b = 0;
}
/* NB. prev_p passed in %eax, next_p passed in %edx */
void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
{
+ extern struct desc_struct idt_table[];
struct thread_struct *prev = &prev_p->thread,
*next = &next_p->thread;
struct tss_struct *tss = init_tss + smp_processor_id();
unlazy_fpu(prev_p);
+ /* Switch the fast-trap handler. */
+ CLEAR_FAST_TRAP(&prev_p->thread);
+ SET_FAST_TRAP(&next_p->thread);
+
tss->esp0 = next->esp0;
tss->esp1 = next->esp1;
tss->ss1 = next->ss1;
* Cunning trick to allow arbitrary "INT n" handling.
*
* We set DPL == 0 on all vectors in the IDT. This prevents any INT <n>
- * instruction from trapping to the appropriate vector, when that might not
+ * instruction from trapping to the appropriate vector, when that might not
* be expected by Xen or the guest OS. For example, that entry might be for
* a fault handler (unlike traps, faults don't increment EIP), or might
* expect an error code on the stack (which a software trap never
* provides), or might be a hardware interrupt handler that doesn't like
- * being called spuriously.
+ * being called spuriously.
*
* Instead, a GPF occurs with the faulting IDT vector in the error code.
- * Bit 1 is set to indicate that an IDT entry caused the fault.
- * Bit 0 is clear to indicate that it's a software fault, not hardware.
+ * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is
+ * clear to indicate that it's a software fault, not hardware.
*
- * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is okay
- * because they can only be triggered by an explicit DPL-checked instruction.
- * The DPL specified by the guest OS for these vectors is NOT CHECKED!!
+ * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is
+ * okay because they can only be triggered by an explicit DPL-checked
+ * instruction. The DPL specified by the guest OS for these vectors is NOT
+ * CHECKED!!
*/
if ( (error_code & 3) == 2 )
{
ti = current->thread.traps + (error_code>>3);
if ( ti->dpl >= (regs->xcs & 3) )
{
+ if ( (error_code>>3)==0x80 ) { printk("!!!\n"); BUG(); }
gtb->flags = GTBF_TRAP_NOCODE;
gtb->cs = ti->cs;
gtb->eip = ti->address;
}
+long do_set_fast_trap(int idx)
+{
+ trap_info_t *ti;
+
+ /* Index 0 is special: it disables fast traps. */
+ if ( idx == 0 )
+ {
+ CLEAR_FAST_TRAP(¤t->thread);
+ memset(idt_table+current->thread.fast_trap_idx, 0, 8);
+ current->thread.fast_trap_idx = 0x20;
+ current->thread.fast_trap_desc.a = 0;
+ current->thread.fast_trap_desc.b = 0;
+ return 0;
+ }
+
+ /*
+ * We only fast-trap vectors 0x20-0x2f, and vector 0x80.
+ * The former range is used by Windows and MS-DOS.
+ * Vector 0x80 is used by Linux and the BSD variants.
+ */
+ if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) ) return -1;
+
+ ti = current->thread.traps + idx;
+
+ CLEAR_FAST_TRAP(¤t->thread);
+
+ current->thread.fast_trap_idx = idx;
+ current->thread.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
+ current->thread.fast_trap_desc.b =
+ (ti->address & 0xffff0000) | 0x8f00 | (ti->dpl&3)<<13;
+
+ SET_FAST_TRAP(¤t->thread);
+
+ return 0;
+}
+
+
long do_fpu_taskswitch(void)
{
current->flags |= PF_GUEST_STTS;
#define SA_SHIRQ 0x04000000
#define TIMER_IRQ 0
-/* 256 in architecture, minus 16 allocated to processor. */
-#define NR_IRQS 224
extern void disable_irq(unsigned int);
extern void disable_irq_nosync(unsigned int);
* IDT vectors usable for external interrupt sources start
* at 0x20:
*/
-#define FIRST_EXTERNAL_VECTOR 0x20
+#define FIRST_EXTERNAL_VECTOR 0x30
-#define SYSCALL_VECTOR 0x80 /* application -> OS */
-#define KDBENTER_VECTOR 0x81 /* anyone -> KDB */
-#define HYPERVISOR_CALL_VECTOR 0x82 /* OS -> monitor*/
+#define NR_IRQS (256 - FIRST_EXTERNAL_VECTOR)
+
+#define HYPERVISOR_CALL_VECTOR 0x82
/*
- * Vectors 0x20-0x2f are used for ISA interrupts.
+ * Vectors 0x30-0x3f are used for ISA interrupts.
*/
/*
#define LOCAL_TIMER_VECTOR 0xef
/*
- * First APIC vector available to drivers: (vectors 0x30-0xee)
- * we start at 0x31 to spread out vectors evenly between priority
- * levels. (0x80 is the syscall vector)
+ * First APIC vector available to drivers: (vectors 0x40-0xee)
+ * we start at 0x41 to spread out vectors evenly between priority
+ * levels. (0x82 is the syscall vector)
*/
-#define FIRST_DEVICE_VECTOR 0x31
+#define FIRST_DEVICE_VECTOR 0x41
#define FIRST_SYSTEM_VECTOR 0xef
extern int irq_vector[NR_IRQS];
#include <asm/page.h>
#include <asm/types.h>
#include <asm/cpufeature.h>
+#include <asm/desc.h>
#include <xeno/config.h>
#include <hypervisor-ifs/hypervisor-if.h>
/* floating point info */
union i387_union i387;
/* Trap info. */
+ int fast_trap_idx;
+ struct desc_struct fast_trap_desc;
trap_info_t traps[256];
};
+#define CLEAR_FAST_TRAP(_p) \
+ (memset(idt_table + (_p)->fast_trap_idx, 0, 8))
+#define SET_FAST_TRAP(_p) \
+ (memcpy(idt_table + (_p)->fast_trap_idx, &((_p)->fast_trap_desc), 8))
+
#define INIT_THREAD { \
sizeof(idle0_stack) + (long) &idle0_stack, /* esp0 */ \
0, 0, 0, 0, 0, 0, \
{ [0 ... 7] = 0 }, /* debugging registers */ \
0, 0, 0, \
{ { 0, }, }, /* 387 state */ \
+ 0, { 0, 0 }, \
{ {0} } /* io permissions */ \
}
#define __HYPERVISOR_set_debugreg 11
#define __HYPERVISOR_get_debugreg 12
#define __HYPERVISOR_update_descriptor 13
+#define __HYPERVISOR_set_fast_trap 14
#define TRAP_INSTR "int $0x82"
void __init trap_init(void)
{
HYPERVISOR_set_trap_table(trap_table);
+ HYPERVISOR_set_fast_trap(SYSCALL_VECTOR);
cpu_init();
}
: "=a" (ret) : "0" (__HYPERVISOR_set_gdt),
"b" (pa), "c" (word1), "d" (word2) );
+ return ret;
+}
+
+static inline int HYPERVISOR_set_fast_trap(int idx)
+{
+ int ret;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret) : "0" (__HYPERVISOR_set_fast_trap),
+ "b" (idx) );
return ret;
}